package br.unicamp.ic.sgct.server.dominio.entidades;

import java.io.Serializable;
import java.util.Date;



import javax.persistence.CascadeType;
import javax.persistence.Column;

import javax.persistence.Entity;

import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;

import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;

import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;

import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import br.unicamp.ic.sgct.client.dominio.to.UsuarioTO;

@Entity(name = "Usuario")
@Table(name = "T_USUARIO")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TIPO", discriminatorType = DiscriminatorType.STRING)
@NamedQueries({
    @NamedQuery(name = Usuario.findByEmailSenha, query = "SELECT  entity  FROM Usuario entity where  lower(entity.email) like ?1 and senha like ?2"),
    @NamedQuery(name = Usuario.findByEmail, query = "SELECT  entity  FROM Usuario entity where  lower(entity.email) like ?1"),
    @NamedQuery(name = Usuario.findByUsername, query = "SELECT  entity  FROM Usuario entity where  entity.username=?1"),
    @NamedQuery(name = Usuario.findByIdPessoaAndIdConferencia , query = "SELECT  entity  FROM Usuario entity where  entity.pessoa.idPessoa=?1 and entity.conferencia.id=?2")
})
public abstract class Usuario implements Serializable {

    private static final long serialVersionUID = -2752317109252197973L;
    public final static String findByEmailSenha = "Usuario.findByEmailSenha";
    public final static String findByEmail = "Usuario.findByEmail";
    public final static String findByUsername = "Usuario.findByUsername";
    public final static String findByIdPessoaAndIdConferencia = "Usuario.findByIdPessoaAndIdConferencia";

    @Id
    @Column(name = "id_usuario", unique = true)
    @TableGenerator(name = "USUARIO_GEN", allocationSize = 1, initialValue = 1, table = "T_ID", pkColumnName = "key", valueColumnName = "valor", pkColumnValue = "ID_USUARIO")
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "USUARIO_GEN")
    protected Long id;
    @Column(length = 8)
    private String username;
    @Column(length = 8)
    protected String senha;
    @Column(length = 1)
    protected String inscricaoAtiva;
    @Column(length = 30)
    protected String email;
    @OneToOne(optional = true, targetEntity = Pessoa.class, cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.PERSIST})
    @JoinColumn(name = "id_pessoa", nullable = true)
    protected Pessoa pessoa;
    @Column
    @Temporal(value = TemporalType.DATE)
    protected Date dataEfetivacaoPagto;
    @ManyToOne(fetch = FetchType.LAZY, targetEntity = Conferencia.class)
    @JoinColumn(name = "fk_id_conf", nullable = true)
    private Conferencia conferencia;
    

    public Usuario() {
        super();
    }

    /**
     *
     * @param idUsuario
     */
    public Usuario(Long id) {
        super();
        this.id = id;
    }

    /**
     *
     * @param senha
     * @param email
     * @param pessoa
     */
    public Usuario(String senha, String email, Pessoa pessoa) {
        super();
        this.senha = senha;
        this.email = email;
        this.pessoa = pessoa;
    }

    public Usuario(UsuarioTO to) {
        this.id = to.getId();
        this.senha = to.getSenha();
        this.email = to.getEmail();
        this.username = to.getUsername();
        this.inscricaoAtiva = to.getInscricaoAtiva();
        this.dataEfetivacaoPagto = to.getDataEfetivacaoPagto();
        this.pessoa = new Pessoa(to.getPessoa());

    }

    //~ getters & setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public String getInscricaoAtiva() {
        return inscricaoAtiva;
    }

    public void setInscricaoAtiva(String inscricaoAtiva) {
        this.inscricaoAtiva = inscricaoAtiva;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Pessoa getPessoa() {
        return pessoa;
    }

    public void setPessoa(Pessoa pessoa) {
        this.pessoa = pessoa;
    }

    public Date getDataEfetivacaoPagto() {
        return dataEfetivacaoPagto;
    }

    public void setDataEfetivacaoPagto(Date dataEfetivacaoPagto) {
        this.dataEfetivacaoPagto = dataEfetivacaoPagto;
    }

    /**
     * Constructs a <code>String</code> with all attributes
     * in name = value format.
     *
     * @return a <code>String</code> representation
     * of this object.
     */
    public String toString() {
        final String TAB = "    ";

        String retValue = "";

        retValue = "Usuario ( "
                + super.toString() + TAB
                + "id = " + this.id + TAB
                + "senha = " + this.senha + TAB
                + "inscricaoAtiva = " + this.senha + TAB
                + "email = " + this.email + TAB
                + "pessoa = " + (this.pessoa != null ? this.pessoa.toString() + TAB : "NULL ")
                + " )";

        return retValue;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        /**
        if (getClass() != obj.getClass()) {
        return false;
        }
         */
        if (!(obj instanceof Usuario)) {
            return false;
        }
        final Usuario other = (Usuario) obj;
        if (this.id != other.id) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 97 * hash + (this.id == null ? 0 : (int) (this.id ^ (this.id >>> 32)));
        return hash;
    }

    public abstract UsuarioTO getTo();

    protected void populaTO(UsuarioTO to) {
        to.setEmail(email);
        to.setId(id);
        to.setInscricaoAtiva(inscricaoAtiva);
        to.setSenha(senha);
        to.setPessoa(pessoa.getTo());
        to.setUsername(getUsername());
        to.setDataEfetivacaoPagto(dataEfetivacaoPagto);
    }

    /**
     * @return the conferencia
     */
    public Conferencia getConferencia() {
        return conferencia;
    }

    /**
     * @param conferencia the conferencia to set
     */
    public void setConferencia(Conferencia conferencia) {
        this.conferencia = conferencia;
    }

    /**
     * @return the username
     */
    public String getUsername() {
        return username;
    }

    /**
     * @param username the username to set
     */
    public void setUsername(String username) {
        this.username = username;
    }
}
